home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Leisure Game Pak 1
/
Leisure Game Pak I.iso
/
lpgame1
/
04
/
source
/
tiles.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-08-17
|
12KB
|
300 lines
UNIT TILES;
INTERFACE
CONST PUSHED_TILE = TRUE; (* modes for drawing tiles *)
NOT_PUSHED_TILE = NOT(PUSHED_TILE);
MAX_COL_ROW = 50; (* max. no of ROWs, COLs *)
(* color constants are of COLOR_TYPE *)
BLACK = 0;
DKGREY = 1;
GREY = 2;
CLR_MARKED = 3; (* BLUE *)
CLR_VISIBLE1 = 6; (* colors 6..13 are used for visible1..8 *)
CLR_VISIBLE_MINE= 14;
WHITE = 15; (* for mouse *)
BY_CONTENTS = 16; (* color depends on tile contents *)
TYPE COLOR_TYPE = 0..16;
(* the contents of a field, note that hidden9, marked9 are never
used ... they're needed to keep equal distances: 0..mine *)
CONTENTS_TYPE = (hidden0, hidden1, hidden2, hidden3, hidden4,
hidden5, hidden6, hidden7, hidden8, hidden9,
hidden_mine,
visible0, visible1, visible2, visible3, visible4,
visible5, visible6, visible7, visible8, visible9,
visible_mine,
marked0, marked1, marked2, marked3, marked4,
marked5, marked6, marked7, marked8, marked9,
marked_mine);
PUSH_MODE_TYPE = BOOLEAN;
COORDS_TYPE = RECORD
x, y : WORD;
END;
SCENE_TYPE = RECORD (* cols, rows are in [0..NumX-1] *)
NumCols, NumRows : BYTE;
(* the size of a tile *)
Size : COORDS_TYPE;
Origin : COORDS_TYPE;
NumMines : BYTE;
TimeLimit : WORD; (* in secs *)
END;
(* the coordinates of a hexagon *)
HEXAGON_TYPE = ARRAY [1..6] OF COORDS_TYPE;
(* top, topleft, topright, middle, bottomleft, bottomright, bottom *)
SEGMENT_TYPE = (t, tl, tr, m, bl, br, b);
(* the tile_type defines the tiles' appearance *)
TILE_TYPE = RECORD
Size : COORDS_TYPE;
inner_min : COORDS_TYPE;
inner_max : COORDS_TYPE;
Seg_Coords : ARRAY [SEGMENT_TYPE] OF HEXAGON_TYPE;
END;
COL_ROW_TYPE = -2..(MAX_COL_ROW + 2); (* ±2 for the exploding mines *)
CONST HIDDEN = [hidden0 .. hidden_mine];
VISIBLE = [visible0.. visible_mine];
MARKED = [marked0 .. marked_mine];
VAR TileImage : ARRAY [PUSH_MODE_TYPE] OF POINTER;
(* the supplied procedures *)
(* get_tile_pos returns the position of tile (col,row) in scene *)
PROCEDURE get_tile_pos(VAR scene : SCENE_TYPE;
col, row : COL_ROW_TYPE;
VAR x, y : WORD);
(* get_tile_middle returns the middle of tile (col,row) in scene *)
PROCEDURE get_tile_middle(VAR scene : SCENE_TYPE;
col, row : COL_ROW_TYPE;
VAR x, y : WORD);
(* draw_contents draws the tile's contents *)
PROCEDURE draw_contents(VAR tile : TILE_TYPE;
x, y : WORD;
contents : CONTENTS_TYPE;
color : COLOR_TYPE);
(* draw_tile draws one tile with contents in scene, col, row *)
(* scene is given as VAR to speed things up a little ... *)
PROCEDURE draw_tile(VAR scene : SCENE_TYPE;
VAR tile : TILE_TYPE;
col, row : COL_ROW_TYPE;
contents : CONTENTS_TYPE);
(* generate_tile computes tile's size and generates its graphics *)
(* it draws a tile on the screen, screen should be dimmer before call
and cleared up after call *)
PROCEDURE generate_tile(scene : SCENE_TYPE; VAR tile : TILE_TYPE);
IMPLEMENTATION
USES GRAPH;
TYPE DIGIT_TYPE = SET OF SEGMENT_TYPE;
(* the segments to be illuminated for each symbol *)
(* note that only 1..8 are needed for the playfield, 0 and 9 are
included to enable display every number (e.g. the time) *)
CONST DIGIT : ARRAY [visible0..marked0] OF DIGIT_TYPE =
( [t, tl, tr, bl, br, b], (* 0 *)
[tr, br], (* 1 *)
[t, tr, m, bl, b], (* 2 *)
[t, tr, m, br, b], (* 3 *)
[tl, tr, m, br], (* 4 *)
[t, tl, m, br, b], (* 5 *)
[t, tl, m, bl, br, b], (* 6 *)
[t, tr, br], (* 7 *)
[t, tl, tr, m, bl, br, b], (* 8 *)
[t, tl, tr, m, br, b], (* 9 *)
[tl, m, bl, br, b], (* b *) (* visible_mine *)
[t, tl, m, bl] (* F *) (* marked0 = Flag *)
);
ORIGINAL_TILE : TILE_TYPE =
( Size: (x: 100; y: 100);
inner_min: (x: 10; y: 10);
inner_max: (x: 89; y: 89);
Seg_Coords: (((x: 33; y: 29), (x: 28; y: 24), (x: 33; y: 19),
(x: 66; y: 19), (x: 71; y: 24), (x: 66; y: 29)), (* t *)
((x: 30; y: 31), (x: 25; y: 26), (x: 20; y: 31),
(x: 20; y: 42), (x: 25; y: 47), (x: 30; y: 42)), (* tl *)
((x: 79; y: 31), (x: 74; y: 26), (x: 69; y: 31),
(x: 69; y: 42), (x: 74; y: 47), (x: 79; y: 42)), (* tr *)
((x: 33; y: 54), (x: 28; y: 49), (x: 33; y: 44),
(x: 66; y: 44), (x: 71; y: 49), (x: 66; y: 54)), (* m *)
((x: 30; y: 56), (x: 25; y: 51), (x: 20; y: 56),
(x: 20; y: 67), (x: 25; y: 72), (x: 30; y: 67)), (* bl *)
((x: 79; y: 56), (x: 74; y: 51), (x: 69; y: 56),
(x: 69; y: 67), (x: 74; y: 72), (x: 79; y: 67)), (* br *)
((x: 33; y: 80), (x: 28; y: 75), (x: 33; y: 70),
(x: 66; y: 70), (x: 71; y: 75), (x: 66; y: 80)) ) (* b *)
);
(* get_tile_pos returns the position of tile (col,row) in scene *)
PROCEDURE get_tile_pos(VAR scene : SCENE_TYPE;
col, row : COL_ROW_TYPE;
VAR x, y : WORD);
BEGIN
x := scene.Origin.x + SUCC(scene.Size.x) * col;
y := scene.Origin.y + SUCC(scene.Size.y) * row;
END; (* get_tile_pos *)
(* get_tile_middle returns the middle of tile (col,row) in scene *)
PROCEDURE get_tile_middle(VAR scene : SCENE_TYPE;
col, row : COL_ROW_TYPE;
VAR x, y : WORD);
BEGIN
get_tile_pos(scene, col, row, x, y);
INC(x, scene.Size.x DIV 2);
INC(y, scene.Size.y DIV 2);
END; (* get_tile_middle *)
(* draw_contents draws the tile's contents *)
PROCEDURE draw_contents(VAR tile : TILE_TYPE;
x, y : WORD;
contents : CONTENTS_TYPE;
color : COLOR_TYPE);
VAR seg : SEGMENT_TYPE;
hexagon : HEXAGON_TYPE;
hp : 1..6;
BEGIN
IF (color = BY_CONTENTS) THEN
BEGIN (* draw on field, setcolor according to tile contents *)
CASE contents OF
marked0 : color := CLR_MARKED;
visible_mine : color := CLR_VISIBLE_MINE;
ELSE color := CLR_VISIBLE1 + ORD(contents)
- ORD(visible1);
END; (* CASE *)
END (* IF *)
ELSE
BEGIN
SetFillStyle(SOLIDFILL, GREY);
Bar(x + tile.inner_min.x, y + tile.inner_min.y,
x + tile.inner_max.x, y + tile.inner_max.y);
END; (* ELSE *)
SetColor(color); SetFillStyle(SOLIDFILL, color);
SetViewPort(x, y, x+tile.Size.x , y+tile.Size.y, ClipOFF);
FOR seg := t TO b DO
IF (seg IN DIGIT[contents]) THEN
FillPoly(6, tile.Seg_COORDS[seg]);
SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOFF);
END; (* draw_contents *)
(* draw_tile draws one tile with contents in scene, col, row *)
(* scene and tile are given as VAR to speed things up a little ... *)
(* in MP-look the VISIBLE0s are drawn by "uncover_hidden0s()",
in PL-look they are drawn by draw_tile, just like any other tile,
except for the missing symbol *)
PROCEDURE draw_tile(VAR scene : SCENE_TYPE;
VAR tile : TILE_TYPE;
col, row : COL_ROW_TYPE;
contents : CONTENTS_TYPE);
VAR x, y : WORD;
BEGIN
get_tile_pos(scene, col, row, x, y);
IF (contents IN HIDDEN) THEN
PutImage(x, y, TileImage[NOT_PUSHED_TILE]^, NORMALPUT)
ELSE IF (contents IN VISIBLE + MARKED) THEN
BEGIN
(* the marked0 is the only MARKED tile that has
a symbol and color *)
IF (contents IN MARKED) THEN contents := marked0;
(* don't PUSH a MARKED tile, just the VISIBLE ones *)
(* NOTE: PUSHED_TILE = TRUE, therefore the tile is pushed
if contents is in VISIBLE *)
PutImage(x, y, TileImage[contents in VISIBLE]^, NORMALPUT);
(* in PL-look: no symbol for VISIBLE0 *)
IF (contents <> VISIBLE0) THEN
draw_contents(tile, x, y, contents, BY_CONTENTS);
END; (* ELSE IF *)
END; (* draw_tile *)
(* generate_tile computes tile's size and generates its graphics *)
(* it draws a tile on the screen, screen should be dimmed before call
and cleared up after call *)
PROCEDURE generate_tile(scene : SCENE_TYPE; VAR tile : TILE_TYPE);
(* adjust_tile returns a tile adjusted according to the size of the scene *)
PROCEDURE adjust_tile (scene : SCENE_TYPE;
original : TILE_TYPE;
VAR adjusted : TILE_TYPE);
VAR p : BYTE;
seg : SEGMENT_TYPE;
PROCEDURE adjust_coords (VAR coord : COORDS_TYPE);
BEGIN
coord.x := (coord.x * adjusted.Size.x + original.Size.x DIV 2) DIV original.Size.x;
coord.y := (coord.y * adjusted.Size.y + original.Size.y DIV 2) DIV original.Size.y;
END; (* adjust_coords *)
BEGIN
adjusted := original; (* copy the original settings *)
adjusted.Size := scene.Size;
(* adjust inner area *)
adjust_coords(adjusted.inner_min);
adjust_coords(adjusted.inner_max);
(* adjust segment positions for all the segments *)
FOR seg := t TO b DO
(* adjust the 6 segment vertices *)
FOR p := 1 TO 6 DO
adjust_coords(adjusted.Seg_COORDS[seg][p]);
END; (* adjust_tile *)
VAR Triangle : ARRAY[1..3] OF COORDS_TYPE;
BEGIN
(* compute tile's size *)
adjust_tile(scene, ORIGINAL_TILE, tile);
Triangle[1].x := 0; Triangle[1].y := 0;
Triangle[2].x := PRED(tile.Size.x); Triangle[2].y := 0;
Triangle[3].y := PRED(tile.Size.y); Triangle[3].x := 0;
(* generate graphics for pushed tile *)
SetFillStyle(SolidFill, WHITE);
Bar(0, 0, PRED(tile.Size.x), PRED(tile.Size.y));
SetColor(DKGREY); SetFillStyle(SolidFill, DKGREY);
FillPoly(3, Triangle);
SetFillStyle(SolidFill, GREY);
Bar(tile.inner_min.x, tile.inner_min.y, tile.inner_max.x, tile.inner_max.y);
SetColor(GREY);
Line(PRED(tile.Size.x), PRED(tile.Size.Y), tile.inner_max.x, tile.inner_max.y);
GetImage(0,0, PRED(tile.Size.x), PRED(tile.Size.y), TileImage[PUSHED_TILE]^);
(* generate graphics for not pushed tile *)
SetFillStyle(SolidFill, DKGREY);
Bar(0, 0, PRED(tile.Size.x), PRED(tile.Size.y));
SetColor(WHITE); SetFillStyle(SolidFill, WHITE);
FillPoly(3, Triangle);
SetFillStyle(SolidFill, GREY);
Bar(tile.inner_min.x, tile.inner_min.y, tile.inner_max.x, tile.inner_max.y);
SetColor(GREY);
Line(0, 0, tile.inner_min.x, tile.inner_min.y);
GetImage(0,0, PRED(tile.Size.x), PRED(tile.Size.y), TileImage[NOT_PUSHED_TILE]^);
END; (* generate_tile *)
END. (* UNIT TILES *)